package com.vinhvt.effiport.algorithm.genetic;


import com.vinhvt.effiport.algorithm.Algorithm;
import com.vinhvt.effiport.algorithm.genetic.bio.Generation;
import com.vinhvt.effiport.algorithm.genetic.bio.Individual;
import com.vinhvt.effiport.algorithm.genetic.mapper.GeneMap;
import com.vinhvt.effiport.application.sample.Function;
import com.vinhvt.effiport.application.sample.mapper.FunctionGeneMap;
import com.vinhvt.effiport.application.sample.mapper.FunctionMapper;
import com.vinhvt.effiport.financial.ep.Portfolio;
import com.vinhvt.effiport.financial.ep.mapper.EffiPortGeneMap;
import com.vinhvt.effiport.financial.ep.mapper.EffiPortMapper;

public class GeneticAlgorithm implements Algorithm {	
	private static Generation generation = new Generation();	
	private static int tour = GAsParameters.TOUR;
	private static GeneMap solutionSpace;
	
	public Generation solve(GeneMap solutionSpace) throws InterruptedException {
		setSolutionSpace(solutionSpace);
		
		initialize(generation);
		evaluate(generation);	
		//System.out.println("\nBest: " + generation.getBestIndividual().getFitness());
		//System.out.println("Init:" + generation.toString());
		
		for(int i = 0; i < tour; i++) {
//			System.out.println("SIZE:" + generation.getSize());
			evolve(generation);
//			System.out.println("After Evolve:" + generation.getSize());
			evaluate(generation);
//			System.out.println("\nGeneration:" + (i + 1));
//			System.out.println("\nBest: " + generation.getBestIndividual().getFitness());

//			EffiPortMapper mapper = EffiPortMapper.mapping((EffiPortGeneMap)solutionSpace);
			//FunctionMapper mapper = new FunctionMapper((FunctionGeneMap)solutionSpace);
			
//			Individual ind = generation.getBestIndividual();
//			mapper.map2Solution(ind);
			
//			Portfolio port = mapper.getPortfolio();
//			System.out.println(port.toString());
//			System.out.println(ind.toString());
			
//			Function function = mapper.getFunction();
//			System.out.println("-----------RESULT-----------");
//			System.out.println(function.toString());											
		}						
		return generation;
	}
	
	/** Evolve Current Generation*/
	private static void evolve(Generation generation) {
		generation.evolve();
	}
	
	/** <b>Initialize</b> the First <i>Generation</i>*/
	private static void initialize(Generation generation) throws InterruptedException {
		generation.initialize();
	}
	
	/** <em>Evaluate</em> Current Generation by calculating the Fitness of each Individual*/
	private static void evaluate(Generation generation) {				
		int size = generation.getSize();
		for(int i = 0; i < size; i++) {
			Individual individual = generation.getIndividualAt(i);			
			
//			EffiPortMapper mapper = EffiPortMapper.mapping((EffiPortGeneMap)getSolutionSpace());
			
			//FunctionMapper mapper = new FunctionMapper((FunctionGeneMap)getSolutionSpace());
			
//			mapper.map2Solution(individual);
			//individual = mapper.getIndividual();
			Portfolio portfolio = ADNCodex.decipher(individual, solutionSpace);
		}					
	}
		

	public static void setSolutionSpace(GeneMap solutionSpace) {
		GeneticAlgorithm.solutionSpace = solutionSpace;
	}

	public static GeneMap getSolutionSpace() {
		return solutionSpace;
	}
		
	public static Generation getBestIndividuals(Generation gen) {
		Generation result = new Generation();
		
		for(int i = 0; i < gen.getSize(); i++ ) {
			Individual ind = gen.getIndividualAt(i);
			if (ind.getFitness() > 0) {
				result.addIndividual(ind);
			}
		}
		
		return result;		
	}
}
